# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1153.67.15 -> 1.1153.67.16 # arch/ia64/kernel/perfmon.c 1.56 -> 1.57 # (new) -> 1.1 arch/ia64/kernel/perfmon_hpsim.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/08/28 davem@nuts.ninka.net 1.1153.58.10 # [SPARC64]: Make sure init_irqwork_curcpu() is called with PSTATE_IE off. # -------------------------------------------- # 03/08/29 davej@redhat.com 1.1153.1.131 # [AGPGART] Indentation fixes # -------------------------------------------- # 03/08/29 davej@redhat.com 1.1153.1.132 # [AGPGART] Fix missed AGP_APBASE conversion in VIA AGP driver. # -------------------------------------------- # 03/08/28 eranian@hpl.hp.com 1.1153.67.16 # [PATCH] ia64: perfmon2 update # # This patch:- added support for the fake HP simulator PMU. Most of the # code provided by Ian Wienand. Allows a kernel compiled for # the simulator and with CONFIG_PERFMON enabled to boot. # # - cleaned up all CTX_*() macros for the context state changes. # # - relaxed constraint for system-wide session by allowing all # task with access to the context's file descriptor to # manipulate the context as long as they run on the CPU the # context is attached to. # -------------------------------------------- # diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Tue Sep 9 01:05:25 2003 +++ b/arch/ia64/kernel/perfmon.c Tue Sep 9 01:05:25 2003 @@ -58,23 +58,8 @@ #define PFM_CTX_ZOMBIE 4 /* owner of the context is closing it */ #define PFM_CTX_TERMINATED 5 /* the task the context was loaded onto is gone */ -#define CTX_LOADED(c) (c)->ctx_state = PFM_CTX_LOADED -#define CTX_UNLOADED(c) (c)->ctx_state = PFM_CTX_UNLOADED -#define CTX_ZOMBIE(c) (c)->ctx_state = PFM_CTX_ZOMBIE -#define CTX_DESTROYED(c) (c)->ctx_state = PFM_CTX_DESTROYED -#define CTX_MASKED(c) (c)->ctx_state = PFM_CTX_MASKED -#define CTX_TERMINATED(c) (c)->ctx_state = PFM_CTX_TERMINATED - -#define CTX_IS_UNLOADED(c) ((c)->ctx_state == PFM_CTX_UNLOADED) -#define CTX_IS_LOADED(c) ((c)->ctx_state == PFM_CTX_LOADED) -#define CTX_IS_ZOMBIE(c) ((c)->ctx_state == PFM_CTX_ZOMBIE) -#define CTX_IS_MASKED(c) ((c)->ctx_state == PFM_CTX_MASKED) -#define CTX_IS_TERMINATED(c) ((c)->ctx_state == PFM_CTX_TERMINATED) -#define CTX_IS_DEAD(c) ((c)->ctx_state == PFM_CTX_TERMINATED || (c)->ctx_state == PFM_CTX_ZOMBIE) - #define PFM_INVALID_ACTIVATION (~0UL) - /* * depth of message queue */ @@ -649,6 +634,7 @@ DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); DEFINE_PER_CPU(unsigned long, pmu_activation_number); + /* forward declaration */ static struct file_operations pfm_file_ops; @@ -659,7 +645,13 @@ static void pfm_lazy_save_regs (struct task_struct *ta); #endif -#if defined(CONFIG_ITANIUM) +/* + * the HP simulator must be first because + * CONFIG_IA64_HP_SIM is independent of CONFIG_MCKINLEY or CONFIG_ITANIUM + */ +#if defined(CONFIG_IA64_HP_SIM) +#include "perfmon_hpsim.h" +#elif defined(CONFIG_ITANIUM) #include "perfmon_itanium.h" #elif defined(CONFIG_MCKINLEY) #include "perfmon_mckinley.h" @@ -953,13 +945,15 @@ struct thread_struct *th = &task->thread; unsigned long mask; unsigned long psr, val; - int i; + int i, is_system; + + is_system = ctx->ctx_fl_system; if (task != current) { printk(KERN_ERR "perfmon.%d: invalid task[%d] current[%d]\n", __LINE__, task->pid, current->pid); return; } - if (CTX_IS_MASKED(ctx) == 0) { + if (ctx->ctx_state != PFM_CTX_MASKED) { printk(KERN_ERR "perfmon.%d: task[%d] current[%d] invalid state=%d\n", __LINE__, task->pid, current->pid, ctx->ctx_state); return; @@ -975,7 +969,7 @@ * * system-wide session are pinned and self-monitoring */ - if (ctx->ctx_fl_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { + if (is_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { /* disable dcr pp */ ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) & ~IA64_DCR_PP); pfm_clear_psr_pp(); @@ -1022,7 +1016,7 @@ /* * now restore PSR */ - if (ctx->ctx_fl_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { + if (is_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { /* enable dcr pp */ ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) | IA64_DCR_PP); ia64_srlz_i(); @@ -1825,6 +1819,7 @@ void *smpl_buf_vaddr = NULL; void *smpl_buf_addr = NULL; int free_possible = 1; + int state, is_system; { u64 psr = pfm_get_psr(); BUG_ON((psr & IA64_PSR_I) == 0UL); @@ -1850,6 +1845,11 @@ PROTECT_CTX(ctx, flags); + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; + + task = PFM_CTX_TASK(ctx); + /* * remove our file from the async queue, if we use it */ @@ -1859,11 +1859,10 @@ DPRINT(("[%d] after async_queue=%p\n", current->pid, ctx->ctx_async_queue)); } - task = PFM_CTX_TASK(ctx); - DPRINT(("[%d] ctx_state=%d\n", current->pid, ctx->ctx_state)); + DPRINT(("[%d] ctx_state=%d\n", current->pid, state)); - if (CTX_IS_UNLOADED(ctx) || CTX_IS_TERMINATED(ctx)) { + if (state == PFM_CTX_UNLOADED || state == PFM_CTX_TERMINATED) { goto doit; } @@ -1884,7 +1883,7 @@ * * We need to release the resource on the ORIGINAL cpu. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); @@ -1900,9 +1899,10 @@ task->thread.pfm_context = NULL; ctx->ctx_task = NULL; - CTX_UNLOADED(ctx); + ctx->ctx_state = state = PFM_CTX_UNLOADED; pfm_unreserve_session(ctx, 1 , ctx->ctx_cpu); + } else #endif /* CONFIG_SMP */ { @@ -1914,19 +1914,20 @@ */ pfm_context_unload(ctx, NULL, 0, regs); - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; - DPRINT(("[%d] ctx_state=%d\n", current->pid, ctx->ctx_state)); + DPRINT(("[%d] ctx_state=%d\n", current->pid, state)); } goto doit; } + /* * The task is currently blocked or will block after an overflow. * we must force it to wakeup to get out of the * MASKED state and transition to the unloaded state by itself */ - if (CTX_IS_MASKED(ctx) && CTX_OVFL_NOBLOCK(ctx) == 0) { + if (state == PFM_CTX_MASKED && CTX_OVFL_NOBLOCK(ctx) == 0) { /* * set a "partial" zombie state to be checked @@ -1949,7 +1950,7 @@ */ up(&ctx->ctx_restart_sem); - DPRINT(("waking up ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); + DPRINT(("waking up ctx_state=%d for [%d]\n", state, current->pid)); /* * put ourself to sleep waiting for the other @@ -1971,24 +1972,26 @@ */ schedule(); - DPRINT(("woken up ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); PROTECT_CTX(ctx, flags); + /* reload state, may have changed during opening of critical section */ + state = ctx->ctx_state; + remove_wait_queue(&ctx->ctx_zombieq, &wait); set_current_state(TASK_RUNNING); /* * context is terminated at this point */ - DPRINT(("after zombie wakeup ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); + DPRINT(("after zombie wakeup ctx_state=%d for [%d]\n", state, current->pid)); } else { #ifdef CONFIG_SMP /* * switch context to zombie state */ - CTX_ZOMBIE(ctx); + ctx->ctx_state = PFM_CTX_ZOMBIE; DPRINT(("zombie ctx for [%d]\n", task->pid)); /* @@ -2032,7 +2035,6 @@ ctx->ctx_smpl_hdr = NULL; } - DPRINT(("[%d] ctx_state=%d free_possible=%d vaddr=%p addr=%p size=%lu\n", current->pid, ctx->ctx_state, @@ -2047,7 +2049,7 @@ * UNLOADED and TERMINATED mean that the session has already been * unreserved. */ - if (CTX_IS_ZOMBIE(ctx)) { + if (state == PFM_CTX_ZOMBIE) { pfm_unreserve_session(ctx, ctx->ctx_fl_system , ctx->ctx_cpu); } @@ -2655,7 +2657,7 @@ /* * context is unloaded */ - CTX_UNLOADED(ctx); + ctx->ctx_state = PFM_CTX_UNLOADED; /* * initialization of context's flags @@ -2787,7 +2789,7 @@ if (flag == PFM_PMD_NO_RESET) return; - if (CTX_IS_MASKED(ctx)) { + if (ctx->ctx_state == PFM_CTX_MASKED) { pfm_reset_regs_masked(ctx, ovfl_regs, flag); return; } @@ -2836,27 +2838,30 @@ unsigned long value; unsigned long smpl_pmds, reset_pmds; unsigned int cnum, reg_flags, flags; - int i, can_access_pmu = 0, is_loaded; - int is_monitor, is_counting; + int i, can_access_pmu = 0, is_loaded, is_system; + int is_monitor, is_counting, state; int ret = -EINVAL; #define PFM_CHECK_PMC_PM(x, y, z) ((x)->ctx_fl_system ^ PMC_PM(y, z)) - if (CTX_IS_DEAD(ctx)) return -EINVAL; + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -2893,7 +2898,6 @@ goto error; } - if (is_counting) { pfm_monitor_t *p = (pfm_monitor_t *)&value; /* @@ -2975,7 +2979,7 @@ * make sure we do not try to reset on * restart because we have established new values */ - if (CTX_IS_MASKED(ctx)) ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; + if (state == PFM_CTX_MASKED) ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; } /* * Needed in case the user does not initialize the equivalent @@ -3007,7 +3011,7 @@ /* * write thread state */ - if (ctx->ctx_fl_system == 0) thread->pmcs[cnum] = value; + if (is_system == 0) thread->pmcs[cnum] = value; /* * write hardware register if we can @@ -3067,13 +3071,16 @@ pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned long value, hw_value; unsigned int cnum; - int i, can_access_pmu = 0; - int is_counting, is_loaded; + int i, can_access_pmu = 0, state; + int is_counting, is_loaded, is_system; int ret = -EINVAL; - if (CTX_IS_DEAD(ctx)) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; /* * on both UP and SMP, we can only write to the PMC when the task is @@ -3081,16 +3088,16 @@ */ if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -3179,7 +3186,7 @@ * make sure we do not try to reset on * restart because we have established new values */ - if (is_counting && CTX_IS_MASKED(ctx)) { + if (is_counting && state == PFM_CTX_MASKED) { ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; } @@ -3187,7 +3194,7 @@ /* * write thread state */ - if (ctx->ctx_fl_system == 0) thread->pmds[cnum] = hw_value; + if (is_system == 0) thread->pmds[cnum] = hw_value; /* * write hardware register if we can @@ -3265,35 +3272,40 @@ unsigned long val = 0UL, lval ; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned int cnum, reg_flags = 0; - int i, is_loaded, can_access_pmu = 0; + int i, can_access_pmu = 0, state; + int is_loaded, is_system; int ret = -EINVAL; - if (CTX_IS_ZOMBIE(ctx)) return -EINVAL; - /* * access is possible when loaded only for * self-monitoring tasks or in UP mode */ - is_loaded = CTX_IS_LOADED(ctx); + + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_ZOMBIE) return -EINVAL; if (is_loaded) { thread = &ctx->ctx_task->thread; /* - * this can be true when not self-monitoring only in UP - */ - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task? 1 : 0; - - if (can_access_pmu) ia64_srlz_d(); - /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + /* + * this can be true when not self-monitoring only in UP + */ + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + + if (can_access_pmu) ia64_srlz_d(); } + DPRINT(("enter loaded=%d access_pmu=%d ctx_state=%d\n", is_loaded, can_access_pmu, @@ -3334,7 +3346,7 @@ * if context is zombie, then task does not exist anymore. * In this case, we use the full value saved in the context (pfm_flush_regs()). */ - val = CTX_IS_LOADED(ctx) ? thread->pmds[cnum] : 0UL; + val = state == PFM_CTX_LOADED ? thread->pmds[cnum] : 0UL; } if (PMD_IS_COUNTING(cnum)) { @@ -3628,7 +3640,7 @@ if (rst_ctrl.bits.mask_monitoring == 0) { DPRINT(("resuming monitoring for [%d]\n", task->pid)); - if (CTX_IS_MASKED(ctx)) pfm_restore_monitoring(task); + if (state == PFM_CTX_MASKED) pfm_restore_monitoring(task); } else { DPRINT(("keeping monitoring stopped for [%d]\n", task->pid)); @@ -3643,7 +3655,7 @@ /* * back to LOADED state */ - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; return 0; } @@ -3706,30 +3718,34 @@ dbreg_t dbreg; unsigned int rnum; int first_time; - int ret = 0; - int i, can_access_pmu = 0, is_loaded; + int ret = 0, state; + int i, can_access_pmu = 0; + int is_system, is_loaded; if (pmu_conf.use_rr_dbregs == 0) return -EINVAL; - if (CTX_IS_DEAD(ctx)) return -EINVAL; + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); /* * on both UP and SMP, we can only write to the PMC when the task is * the owner of the local PMU. */ if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } /* @@ -3758,7 +3774,7 @@ */ LOCK_PFS(); - if (first_time && ctx->ctx_fl_system) { + if (first_time && is_system) { if (pfm_sessions.pfs_ptrace_use_dbregs) ret = -EBUSY; else @@ -3906,16 +3922,19 @@ { struct pt_regs *tregs; struct task_struct *task = PFM_CTX_TASK(ctx); + int state, is_system; + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; - if (CTX_IS_LOADED(ctx) == 0 && CTX_IS_MASKED(ctx) == 0) return -EINVAL; + if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } @@ -3925,7 +3944,7 @@ * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * Update local PMU first * @@ -3985,15 +4004,19 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct pt_regs *tregs; + int state, is_system; - if (CTX_IS_LOADED(ctx) == 0) return -EINVAL; + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; + + if (state != PFM_CTX_LOADED) return -EINVAL; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } @@ -4003,7 +4026,7 @@ * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * set user level psr.pp for the caller @@ -4055,7 +4078,6 @@ */ ia64_psr(tregs)->up = 1; } - return 0; } @@ -4121,11 +4143,14 @@ unsigned long *pmcs_source, *pmds_source; int the_cpu; int ret = 0; + int state, is_system; + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; /* * can only load from unloaded or terminated state */ - if (CTX_IS_UNLOADED(ctx) == 0 && CTX_IS_TERMINATED(ctx) == 0) { + if (state != PFM_CTX_UNLOADED && state != PFM_CTX_TERMINATED) { DPRINT(("[%d] cannot load to [%d], invalid ctx_state=%d\n", current->pid, req->load_pid, @@ -4151,7 +4176,7 @@ /* * system wide is self monitoring only */ - if (ctx->ctx_fl_system && task != current) { + if (is_system && task != current) { DPRINT(("system wide is self monitoring only current=%d load_pid=%d\n", current->pid, req->load_pid)); @@ -4191,7 +4216,7 @@ /* * now reserve the session */ - ret = pfm_reserve_session(current, ctx->ctx_fl_system, the_cpu); + ret = pfm_reserve_session(current, is_system, the_cpu); if (ret) goto error; ret = -EBUSY; @@ -4216,15 +4241,14 @@ pfm_reset_msgq(ctx); - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; /* * link context to task */ ctx->ctx_task = task; - if (ctx->ctx_fl_system) { - + if (is_system) { /* * we load as stopped */ @@ -4250,7 +4274,7 @@ */ if (task == current) { - if (ctx->ctx_fl_system == 0) { + if (is_system == 0) { /* allow user level control */ ia64_psr(regs)->sp = 0; @@ -4318,14 +4342,14 @@ /* * release task, there is now a link with the context */ - if (ctx->ctx_fl_system == 0 && task != current) { + if (is_system == 0 && task != current) { pfm_put_task(task); if (ret == 0) { ret = pfm_check_task_exist(ctx); if (ret) { - CTX_UNLOADED(ctx); - ctx->ctx_task = NULL; + ctx->ctx_state = PFM_CTX_UNLOADED; + ctx->ctx_task = NULL; } } } @@ -4347,40 +4371,34 @@ { struct task_struct *task = PFM_CTX_TASK(ctx); struct pt_regs *tregs; + int state, is_system; DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1)); + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; + /* * unload only when necessary */ - if (CTX_IS_TERMINATED(ctx) || CTX_IS_UNLOADED(ctx)) { + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_UNLOADED) { DPRINT(("[%d] ctx_state=%d, nothing to do\n", current->pid, ctx->ctx_state)); return 0; } /* - * In system wide and when the context is loaded, access can only happen - * when the caller is running on the CPU being monitored by the session. - * It does not have to be the owner (ctx_task) of the context per se. - */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { - DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); - return -EBUSY; - } - - /* * clear psr and dcr bits */ pfm_stop(ctx, NULL, 0, regs); - CTX_UNLOADED(ctx); + ctx->ctx_state = state = PFM_CTX_UNLOADED; /* * in system mode, we need to update the PMU directly * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * Update cpuinfo @@ -4524,7 +4542,7 @@ if (ret) { printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, ctx->ctx_state, ret); } - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; DPRINT(("ctx terminated by [%d]\n", task->pid)); pfm_end_notify_user(ctx); @@ -4606,16 +4624,19 @@ pfm_check_task_state(pfm_context_t *ctx, int cmd, unsigned long flags) { struct task_struct *task; + int state; + + state = ctx->ctx_state; task = PFM_CTX_TASK(ctx); if (task == NULL) { - DPRINT(("context %d no task, state=%d\n", ctx->ctx_fd, ctx->ctx_state)); + DPRINT(("context %d no task, state=%d\n", ctx->ctx_fd, state)); return 0; } DPRINT(("context %d state=%d [%d] task_state=%ld must_stop=%d\n", ctx->ctx_fd, - ctx->ctx_state, + state, task->pid, task->state, PFM_CMD_STOPPED(cmd))); @@ -4631,9 +4652,9 @@ /* * context is UNLOADED, MASKED, TERMINATED we are safe to go */ - if (CTX_IS_LOADED(ctx) == 0) return 0; + if (state != PFM_CTX_LOADED == 0) return 0; - if (CTX_IS_ZOMBIE(ctx)) return -EINVAL; + if (state == PFM_CTX_ZOMBIE) return -EINVAL; /* * context is loaded, we must make sure the task is stopped @@ -4653,6 +4674,7 @@ pfm_wait_task_inactive(task); PROTECT_CTX(ctx, flags); + return 0; } @@ -4830,12 +4852,12 @@ } if (rst_ctrl.bits.mask_monitoring == 0) { DPRINT(("resuming monitoring\n")); - if (CTX_IS_MASKED(ctx)) pfm_restore_monitoring(current); + if (ctx->ctx_state == PFM_CTX_MASKED) pfm_restore_monitoring(current); } else { DPRINT(("stopping monitoring\n")); //pfm_stop_monitoring(current, regs); } - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; } } @@ -4869,7 +4891,7 @@ /* * switch to terminated state */ - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; DPRINT(("context <%d> terminated for [%d]\n", ctx->ctx_fd, current->pid)); @@ -4922,7 +4944,7 @@ /* * must be done before we check non-blocking mode */ - if (ctx->ctx_fl_going_zombie || CTX_IS_ZOMBIE(ctx)) goto do_zombie; + if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) goto do_zombie; ovfl_regs = ctx->ctx_ovfl_regs[0]; @@ -4966,7 +4988,7 @@ static int pfm_notify_user(pfm_context_t *ctx, pfm_msg_t *msg) { - if (CTX_IS_ZOMBIE(ctx)) { + if (ctx->ctx_state == PFM_CTX_ZOMBIE) { DPRINT(("ignoring overflow notification, owner is zombie\n")); return 0; } @@ -5049,13 +5071,13 @@ pfm_ovfl_arg_t ovfl_arg; unsigned long mask; unsigned long old_val; - unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; + unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL; unsigned long tstamp; pfm_ovfl_ctrl_t ovfl_ctrl; unsigned int i, has_smpl; int must_notify = 0; - if (unlikely(CTX_IS_ZOMBIE(ctx))) goto stop_monitoring; + if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) goto stop_monitoring; /* * sanity test. Should never happen @@ -5106,10 +5128,9 @@ if (PMC_OVFL_NOTIFY(ctx, i)) ovfl_notify |= 1UL << i; } - DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx " - "ovfl_notify=0x%lx\n", - i, ctx->ctx_pmds[i].val, old_val, - ia64_get_pmd(i) & pmu_conf.ovfl_val, ovfl_pmds, ovfl_notify)); + DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n", + i, ctx->ctx_pmds[i].val, old_val, + ia64_get_pmd(i) & pmu_conf.ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); } /* @@ -5128,7 +5149,7 @@ */ if (has_smpl) { unsigned long start_cycles, end_cycles; - unsigned long pmd_mask, smpl_pmds; + unsigned long pmd_mask; int j, k, ret = 0; int this_cpu = smp_processor_id(); @@ -5257,7 +5278,7 @@ */ if (ovfl_ctrl.bits.mask_monitoring) { pfm_mask_monitoring(task); - CTX_MASKED(ctx); + ctx->ctx_state = PFM_CTX_MASKED; } /* @@ -5553,19 +5574,18 @@ pfm_set_psr_pp(); ia64_srlz_i(); } - { unsigned long val; - val = ia64_get_pmc(4); - if ((val & (1UL<<23)) == 0UL) printk("perfmon: PMU off: pmc4=0x%lx\n", val); - } } void pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_ctxswin) { unsigned long start, end; + pfm_stats[smp_processor_id()].pfm_sysupdt_count++; start = ia64_get_itc(); + pfm_do_syst_wide_update_task(task, info, is_ctxswin); + end = ia64_get_itc(); pfm_stats[smp_processor_id()].pfm_sysupdt_cycles += end-start; } @@ -5591,7 +5611,7 @@ */ flags = pfm_protect_ctx_ctxsw(ctx); - if (CTX_IS_ZOMBIE(ctx)) { + if (ctx->ctx_state == PFM_CTX_ZOMBIE) { struct pt_regs *regs = ia64_task_regs(task); pfm_clear_psr_up(); @@ -5840,7 +5860,7 @@ BUG_ON(psr & IA64_PSR_I); #endif - if (unlikely(CTX_IS_ZOMBIE(ctx))) { + if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) { struct pt_regs *regs = ia64_task_regs(task); BUG_ON(ctx->ctx_smpl_hdr); diff -Nru a/arch/ia64/kernel/perfmon_hpsim.h b/arch/ia64/kernel/perfmon_hpsim.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/kernel/perfmon_hpsim.h Tue Sep 9 01:05:25 2003 @@ -0,0 +1,75 @@ +/* + * This file contains the HP SKI Simulator PMU register description tables + * and pmc checkers used by perfmon.c. + * + * Copyright (C) 2002-2003 Hewlett Packard Co + * Stephane Eranian + * + * File mostly contributed by Ian Wienand + * + * This file is included as a dummy template so the kernel does not + * try to initalize registers the simulator can't handle. + * + * Note the simulator does not (currently) implement these registers, i.e., + * they do not count anything. But you can read/write them. + */ + +#define RDEP(x) (1UL<<(x)) + +#ifndef CONFIG_IA64_HP_SIM +#error "This file should only be included for the HP Simulator" +#endif + +static pfm_reg_desc_t pfm_hpsim_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(4), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(5), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(6), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(7), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(9), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc10 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(10), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc11 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(11), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc12 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(12), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc13 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(13), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc14 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(14), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc15 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(15), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pfm_hpsim_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd1 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd2 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd3 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, +/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(8),0UL, 0UL, 0UL}}, +/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(9),0UL, 0UL, 0UL}}, +/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(13),0UL, 0UL, 0UL}}, +/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(14),0UL, 0UL, 0UL}}, +/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(15),0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +/* + * impl_pmcs, impl_pmds are computed at runtime to minimize errors! + */ +static pmu_config_t pmu_conf={ + .pmu_name = "hpsim", + .pmu_family = 0x7, /* ski emulator reports as Itanium */ + .enabled = 0, + .ovfl_val = (1UL << 32) - 1, + .num_ibrs = 0, /* does not use */ + .num_dbrs = 0, /* does not use */ + .pmd_desc = pfm_hpsim_pmd_desc, + .pmc_desc = pfm_hpsim_pmc_desc +};